<template>
  <div class="app-container">
    <el-form
      :model="queryParams"
      ref="queryForm"
      size="small"
      :inline="true"
      v-show="showSearch"
      label-width="68px"
    >
      <el-form-item label="姓名" prop="name">
        <el-input
          v-model="queryParams.name"
          placeholder="请输入姓名"
          clearable
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item label="手机号" prop="phone">
        <el-input
          v-model="queryParams.phone"
          placeholder="请输入手机号"
          clearable
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item>
        <el-button
          type="primary"
          icon="el-icon-search"
          size="mini"
          @click="handleQuery"
          >搜索</el-button
        >
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
          >重置</el-button
        >
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          icon="el-icon-plus"
          size="mini"
          @click="handleAdd"
          >新增</el-button
        >
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="danger"
          plain
          icon="el-icon-unlock"
          size="mini"
          @click="handleRemoveBan"
          >解除所有封禁</el-button
        >
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="warning"
          plain
          icon="el-icon-download"
          size="mini"
          @click="handleExport"
          >导出</el-button
        >
      </el-col>
      <right-toolbar
        :showSearch.sync="showSearch"
        @queryTable="getList"
      ></right-toolbar>
    </el-row>

    <el-table v-loading="loading" :data="blacklistData">
      <el-table-column type="index" label="序号" width="60" align="center" />
      <el-table-column
        prop="name"
        label="姓名"
        align="center"
        show-overflow-tooltip
      ></el-table-column>
      <el-table-column
        prop="phone"
        label="手机号"
        align="center"
        show-overflow-tooltip
      ></el-table-column>
      <el-table-column
        prop="banningDeadline"
        label="封禁日期"
        width="160"
        align="center"
      ></el-table-column>
      <!-- <el-table-column prop="status" label="状态" align="center" width="80">
        <template slot-scope="scope">
          <el-tag :type="scope.row.status === '0' ? 'danger' : 'success'">
            {{ scope.row.status === "0" ? "封禁中" : "已解封" }}
          </el-tag>
        </template>
      </el-table-column> -->
      <el-table-column
        prop="activityMenuNames"
        label="封禁目录"
        align="center"
        show-overflow-tooltip
      >
        <template slot-scope="scope">
          <el-tooltip placement="top">
            <div slot="content">
              <template
                v-if="
                  scope.row.activityMenuNames &&
                  scope.row.activityMenuNames.length
                "
              >
                <div
                  v-for="(activityName, index) in scope.row.activityMenuNames"
                  :key="index"
                >
                  {{ activityName }}
                </div>
              </template>
              <template v-else>
                <div>无</div>
              </template>
            </div>
            <el-tag
              type="danger"
              v-if="
                scope.row.activityMenuNames &&
                scope.row.activityMenuNames.length
              "
            >
              {{ scope.row.activityMenuNames.length }}个封禁目录
            </el-tag>
            <el-tag type="info" v-else>无封禁目录</el-tag>
          </el-tooltip>
        </template>
      </el-table-column>
      <el-table-column
        label="操作"
        align="center"
        class-name="small-padding fixed-width"
      >
        <template slot-scope="scope">
          <el-button
            size="mini"
            type="text"
            icon="el-icon-edit"
            @click="handleUpdate(scope.row)"
            >修改</el-button
          >
          <el-button
            size="mini"
            type="text"
            icon="el-icon-delete"
            @click="handleDelete(scope.row)"
            >删除</el-button
          >
        </template>
      </el-table-column>
    </el-table>

    <pagination
      v-show="total > 0"
      :total="total"
      :page.sync="queryParams.pageNum"
      :limit.sync="queryParams.pageSize"
      @pagination="getList"
    />

    <!-- 添加或修改黑名单对话框 -->
    <el-dialog
      :title="title"
      :visible.sync="open"
      width="50%"
      append-to-body
      @close="closeDialog"
    >
      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
        <el-row>
          <el-col :span="24">
            <el-form-item label="姓名" prop="name">
              <el-input v-model="form.name" placeholder="请输入姓名" />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="手机号" prop="phone">
              <el-input v-model="form.phone" placeholder="请输入手机号" />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="封禁截止日期" prop="banningDeadline">
              <el-date-picker
                v-model="form.banningDeadline"
                type="date"
                placeholder="选择封禁截止日期"
                :picker-options="pickerOptions"
                value-format="yyyy-MM-dd"
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="封禁目录" prop="activityMenuIds">
              <div style="display: flex; align-items: center">
                <el-checkbox
                  v-model="form.banAllActivities"
                  @change="handleBanAllChange"
                  :disabled="!flatActivityMenu || !flatActivityMenu.length"
                  >所有活动</el-checkbox
                >
              </div>
              <el-row style="margin-top: 10px">
                <el-col :span="24">
                  <el-checkbox-group
                    v-model="form.activityMenuIds"
                    @change="handleCategoriesChange"
                  >
                    <template
                      v-if="flatActivityMenu && flatActivityMenu.length"
                    >
                      <div class="checkbox-container">
                        <div
                          v-for="activity in flatActivityMenu"
                          :key="activity.value"
                          class="checkbox-item"
                        >
                          <el-checkbox
                            :label="activity.value"
                            :key="`checkbox-${activity.value}`"
                            >{{ activity.label }}</el-checkbox
                          >
                        </div>
                      </div>
                    </template>
                    <template v-else>
                      <div class="empty-data">暂无活动数据</div>
                    </template>
                  </el-checkbox-group>
                </el-col>
              </el-row>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm">保 存</el-button>
        <el-button @click="cancel">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import {
  listBlacklist,
  getBlacklist,
  addBlacklist,
  updateBlacklist,
  delBlacklist,
  removeBan,
  exportBlacklist,
} from "@/api/system/blacklist";
import { getMenuTree } from "@/api/activityMenu";

export default {
  name: "BlacklistManagement",
  components: {},
  data() {
    // 创建手机号验证器
    const validatePhone = (rule, value, callback) => {
      if (!value) {
        callback(new Error("手机号不能为空"));
      } else if (!/^1[3-9]\d{9}$/.test(value)) {
        callback(new Error("请输入正确的手机号码"));
      } else {
        callback();
      }
    };

    // 创建日期验证器 - 允许今天或未来日期
    const validateDate = (rule, value, callback) => {
      if (!value) {
        callback(new Error("封禁截止日期不能为空"));
      } else {
        const today = new Date();
        today.setHours(0, 0, 0, 0); // 设置为今天的凌晨

        // 如果是字符串格式，转换为日期对象
        let dateValue = value;
        if (typeof value === "string") {
          dateValue = new Date(value);
        }

        // 设置为凌晨，以便只比较日期部分
        dateValue.setHours(0, 0, 0, 0);

        // 允许今天及以后的日期
        if (dateValue < today) {
          callback(new Error("封禁截止日期不能是过去的日期"));
        } else {
          callback();
        }
      }
    };

    return {
      // 遮罩层
      loading: false,
      // 显示搜索条件
      showSearch: true,
      // 总条数
      total: 0,
      // 黑名单数据
      blacklistData: [],
      // 弹出层标题
      title: "",
      // 是否显示弹出层
      open: false,
      // 活动列表
      activityList: [],
      // 扁平化后的活动菜单列表
      flatActivityMenu: [],
      // 查询参数
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        name: undefined,
        phone: undefined,
      },
      // 表单参数
      form: {},
      // 表单校验
      rules: {
        name: [
          { required: true, message: "姓名不能为空", trigger: "blur" },
          {
            min: 2,
            max: 20,
            message: "姓名长度必须在2到20个字符之间",
            trigger: "blur",
          },
        ],
        phone: [
          { required: true, message: "手机号不能为空", trigger: "blur" },
          { validator: validatePhone, trigger: "blur" },
        ],
        banningDeadline: [
          {
            required: true,
            message: "封禁截止日期不能为空",
            trigger: "change",
          },
          { validator: validateDate, trigger: "change" },
        ],
        activityMenuIds: [
          { required: true, message: "封禁目录不能为空", trigger: "change" },
          {
            type: "array",
            min: 1,
            message: "请至少选择一个封禁目录",
            trigger: "change",
          },
        ],
      },
      pickerOptions: {
        disabledDate(time) {
          // 只禁用昨天及之前的日期，允许选择今天及以后的日期
          return time.getTime() < Date.now() - 8.64e7; // 禁用昨天及更早的时间（86400000毫秒=一天）
        },
      },
    };
  },
  created() {
    this.getList();
    this.getActivities();
  },
  mounted() {
    // 添加对activityMenuIds的深度监听，确保任何变更都能正确反映到全选状态
    this.$watch(
      "form.activityMenuIds",
      (newVal, oldVal) => {
        // 防止循环触发
        // 如果变化是由handleBanAllChange引起的，则忽略本次更新
        if (
          newVal &&
          Array.isArray(newVal) &&
          oldVal &&
          Array.isArray(oldVal)
        ) {
          const allActivityIds = this.flatActivityMenu.map(
            (item) => item.value
          );

          // 如果从空数组变为全部选中，或从全部选中变为空数组，可能是handleBanAllChange触发的
          if (
            (oldVal.length === 0 && newVal.length === allActivityIds.length) ||
            (oldVal.length === allActivityIds.length && newVal.length === 0)
          ) {
            return;
          }
        }

        // 使用requestAnimationFrame确保在下一帧处理
        requestAnimationFrame(() => {
          if (newVal && Array.isArray(newVal)) {
            this.handleCategoriesChange(newVal);
          }
        });
      },
      { deep: true }
    );
  },
  methods: {
    /** 查询黑名单列表 */
    getList() {
      this.loading = true;
      listBlacklist(this.queryParams)
        .then((response) => {
          if (response.code === 200) {
            this.blacklistData = response.rows;
            this.total = response.total;
          } else {
            this.$modal.msgError(response.msg || "获取黑名单列表失败");
          }
        })
        .catch((error) => {
          console.error("获取黑名单列表失败:", error);
          this.$modal.msgError("获取黑名单列表失败，请稍后重试");
        })
        .finally(() => {
          this.loading = false;
        });
    },
    /** 获取活动列表 */
    getActivities() {
      this.loading = true;
      getMenuTree()
        .then((response) => {
          if (response.code === 200) {
            this.activityList = response.data || [];
            // 扁平化处理菜单树，方便在复选框中使用
            this.flatActivityMenu = this.flattenMenuTree(this.activityList);

            // 如果表单已经打开，检查"所有活动"状态
            if (this.open) {
              this.checkAllActivitiesSelected();
            }
          } else {
            this.$modal.msgError(response.msg || "获取活动列表失败");
          }
        })
        .catch((error) => {
          console.error("获取活动列表失败:", error);
          this.$modal.msgError("获取活动列表失败，请稍后重试");
        })
        .finally(() => {
          this.loading = false;
        });
    },
    /** 扁平化菜单树 */
    flattenMenuTree(menuTree) {
      if (!menuTree || !Array.isArray(menuTree)) {
        return [];
      }

      let result = [];

      for (const menu of menuTree) {
        // 不再添加一级菜单，只处理子菜单
        if (menu.child && menu.child.length > 0) {
          // 将子菜单转换为 label/value 格式并添加到结果中
          menu.child.forEach((childMenu) => {
            result.push({
              id: childMenu.id,
              menuName: childMenu.menuName,
              label: childMenu.menuName,
              value: childMenu.id,
            });

            // 如果子菜单还有子菜单，递归处理
            if (childMenu.child && childMenu.child.length > 0) {
              result = result.concat(this.flattenMenuTree([childMenu]));
            }
          });
        }
      }

      return result;
    },
    /** 处理全选活动变化 */
    handleBanAllChange(val) {
      if (!this.flatActivityMenu || !this.flatActivityMenu.length) {
        return;
      }

      // 立即更新UI，避免延迟带来的不好体验
      this.$set(this.form, "banAllActivities", val);

      // 使用requestAnimationFrame确保在浏览器下一帧渲染前执行
      requestAnimationFrame(() => {
        // 获取所有活动ID
        const allIds = this.flatActivityMenu.map((item) => item.value);

        if (val) {
          // 选中所有活动 - 使用新数组避免引用问题
          const newIds = [...allIds];
          this.$set(this.form, "activityMenuIds", newIds);

          // 确保视图已更新，并进行双重检查
          this.$nextTick(() => {
            if (this.form.activityMenuIds.length === allIds.length) {
              this.$set(this.form, "banAllActivities", true);
            }
          });
        } else {
          // 取消选中所有活动
          this.$set(this.form, "activityMenuIds", []);

          // 确保视图已更新，并进行双重检查
          this.$nextTick(() => {
            if (this.form.activityMenuIds.length === 0) {
              this.$set(this.form, "banAllActivities", false);
            }
          });
        }
      });
    },
    /** 处理活动类别变化 */
    handleCategoriesChange(val) {
      // 如果没有可选活动，则禁用全选
      if (!this.flatActivityMenu || !this.flatActivityMenu.length) {
        this.$set(this.form, "banAllActivities", false);
        return;
      }

      // 获取所有活动ID
      const allActivityIds = this.flatActivityMenu.map((item) => item.value);

      // 立即同步处理简单情况
      if (!val || !Array.isArray(val) || val.length === 0) {
        this.$set(this.form, "banAllActivities", false);
        return;
      }

      // 对于可能受到异步影响的情况，使用requestAnimationFrame确保在下一帧处理
      requestAnimationFrame(() => {
        // 再次验证数据有效性
        if (!val || !Array.isArray(val)) {
          this.$set(this.form, "banAllActivities", false);
          return;
        }

        // 判断是否选中了所有活动
        if (val.length === allActivityIds.length) {
          // 数量相同时，还需检查是否完全匹配
          const isAllSelected = allActivityIds.every((id) => val.includes(id));

          // 使用nextTick确保DOM更新后再设置banAllActivities
          this.$nextTick(() => {
            this.$set(this.form, "banAllActivities", isAllSelected);
          });
        } else {
          // 只选择了部分活动
          this.$nextTick(() => {
            this.$set(this.form, "banAllActivities", false);
          });
        }
      });
    },
    /** 获取默认的封禁截止日期（默认为今天） */
    getDefaultBanningDeadline() {
      const today = new Date();

      // 格式化为YYYY-MM-DD
      const year = today.getFullYear();
      const month = (today.getMonth() + 1).toString().padStart(2, "0");
      const day = today.getDate().toString().padStart(2, "0");

      return `${year}-${month}-${day}`;
    },
    /** 表单重置 */
    reset() {
      this.form = {
        id: undefined,
        name: "",
        phone: "",
        banningDeadline: this.getDefaultBanningDeadline(),
        createTime: undefined,
        updateTime: undefined,
        status: "0",
        banAllActivities: false,
        activityMenuIds: [], // 确保初始化为空数组
      };

      // 重置表单后需要确保表单组件的验证状态也被重置
      this.$nextTick(() => {
        if (this.$refs.form) {
          this.$refs.form.clearValidate();
        }
      });
    },
    /** 搜索按钮操作 */
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    /** 重置按钮操作 */
    resetQuery() {
      this.resetForm("queryForm");
      this.handleQuery();
    },
    /** 新增按钮操作 */
    handleAdd() {
      this.reset();
      // 确保复选框组初始化时也会检查
      this.$nextTick(() => {
        this.checkAllActivitiesSelected();
      });
      this.open = true;
      this.title = "添加黑名单";
    },
    /** 修改按钮操作 */
    handleUpdate(row) {
      this.loading = true;
      this.reset();
      getBlacklist(row.id)
        .then((response) => {
          this.loading = false;
          if (response.code === 200) {
            // 获取响应数据并处理
            const data = response.data;

            // 确保表单对象存在
            this.form = {
              ...data,
              // 确保日期格式为字符串，如果后端返回的不是标准格式，需要转换
              banningDeadline: data.banningDeadline,
            };

            this.open = true;
            this.title = "修改黑名单";

            // 在表单打开后，通过nextTick确保DOM更新完成再检查活动状态
            this.$nextTick(() => {
              this.checkAllActivitiesSelected();
            });
          } else {
            this.$modal.msgError(response.msg || "获取黑名单详情失败");
          }
        })
        .catch((error) => {
          this.loading = false;
          console.error("获取黑名单详情失败:", error);
          this.$modal.msgError("获取黑名单详情失败，请稍后重试");
        });
    },
    /** 检查是否选择了所有活动 */
    checkAllActivitiesSelected() {
      // 确保form对象已初始化
      if (!this.form) {
        this.form = {};
      }

      // 确保activityMenuIds已初始化为数组
      if (
        !this.form.activityMenuIds ||
        !Array.isArray(this.form.activityMenuIds)
      ) {
        this.$set(this.form, "activityMenuIds", []);
      }

      // 如果没有可选活动，则设置为false
      if (!this.flatActivityMenu || !this.flatActivityMenu.length) {
        this.$set(this.form, "banAllActivities", false);
        return;
      }

      // 使用requestAnimationFrame确保在浏览器绘制前执行
      requestAnimationFrame(() => {
        // 处理特殊的"all"标记
        if (this.form.activityMenuIds.includes("all")) {
          this.$set(this.form, "banAllActivities", true);
          // 更新选择为所有活动ID (使用数组副本)
          const allActivityIds = this.flatActivityMenu.map(
            (item) => item.value
          );
          this.$set(this.form, "activityMenuIds", [...allActivityIds]);
          return;
        }

        // 获取所有活动ID
        const allActivityIds = this.flatActivityMenu.map((item) => item.value);

        // 判断是否选择了所有活动
        if (this.form.activityMenuIds.length === allActivityIds.length) {
          const allSelected = allActivityIds.every((id) =>
            this.form.activityMenuIds.includes(id)
          );
          this.$set(this.form, "banAllActivities", allSelected);
        } else {
          this.$set(this.form, "banAllActivities", false);
        }
      });
    },
    /** 解除所有封禁 */
    handleRemoveBan() {
      this.$confirm("确定要解除所有黑名单封禁吗？", "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.loading = true;
          return removeBan();
        })
        .then((response) => {
          this.loading = false;
          if (response.code === 200) {
            this.$modal.msgSuccess("解除所有封禁成功");
            this.getList();
          } else {
            this.$modal.msgError(response.msg || "解除所有封禁失败");
          }
        })
        .catch((error) => {
          this.loading = false;
          if (error !== "cancel") {
            console.error("解除封禁失败:", error);
            this.$modal.msgError("解除所有封禁失败，请稍后重试");
          }
        });
    },
    /** 提交按钮 */
    submitForm() {
      this.$refs["form"].validate((valid) => {
        if (!valid) return;

        this.loading = true;
        // 构造提交数据
        const submitData = Object.assign({}, this.form);

        // 处理日期格式 - 由于使用了value-format="yyyy-MM-dd"，日期已经是正确格式
        // 不需要额外处理，如果是Date类型才需要处理
        if (submitData.banningDeadline instanceof Date) {
          submitData.banningDeadline = this.parseTime(
            submitData.banningDeadline,
            "{y}-{m}-{d}"
          );
        }

        // 如果选择了所有活动，确保使用完整的活动ID列表
        if (submitData.banAllActivities) {
          submitData.activityMenuIds = this.flatActivityMenu.map(
            (item) => item.value
          );
        }

        // 设置状态为封禁状态 "0"
        submitData.status = "0";

        // 移除辅助属性，避免发送无用数据
        delete submitData.banAllActivities;

        // 根据是否有ID判断是更新还是新增
        const isUpdate = !!submitData.id;
        const apiCall = isUpdate
          ? updateBlacklist(submitData)
          : addBlacklist(submitData);
        const successMsg = isUpdate ? "修改成功" : "新增成功";
        const errorMsg = isUpdate ? "修改失败" : "新增失败";
        const logMsg = isUpdate ? "修改黑名单失败:" : "新增黑名单失败:";

        // 如果是新增，不需要传递创建时间和更新时间
        if (!isUpdate) {
          delete submitData.createTime;
          delete submitData.updateTime;
        }

        // 执行API调用
        apiCall
          .then((response) => {
            if (response.code === 200) {
              this.$modal.msgSuccess(successMsg);
              this.open = false;
              this.getList();
            } else {
              this.$modal.msgError(response.msg || errorMsg);
            }
          })
          .catch((error) => {
            console.error(logMsg, error);
            this.$modal.msgError(errorMsg + "，请稍后重试");
          })
          .finally(() => {
            this.loading = false;
          });
      });
    },
    /** 删除按钮操作 */
    handleDelete(row) {
      this.$confirm('是否确认删除名称为"' + row.name + '"的黑名单?', "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.loading = true;
          return delBlacklist(row.id);
        })
        .then((response) => {
          this.loading = false;
          if (response.code === 200) {
            this.$modal.msgSuccess("删除成功");
            this.getList();
          } else {
            this.$modal.msgError(response.msg || "删除失败");
          }
        })
        .catch((error) => {
          this.loading = false;
          if (error !== "cancel") {
            console.error("删除黑名单失败:", error);
            this.$modal.msgError("删除黑名单失败，请稍后重试");
          }
        });
    },
    /** 导出按钮操作 */
    handleExport() {
      this.download('blacklist/export', {
        ...this.queryParams
      }, `黑名单_${new Date().getTime()}.xlsx`)
    },
    /** 取消按钮 */
    cancel() {
      this.open = false;
      this.reset();
    },
    /** 关闭弹窗 */
    closeDialog() {
      this.reset();
    },
    /** 获取活动名称 */
    getCategoryName(categoryId) {
      if (this.flatActivityMenu && this.flatActivityMenu.length) {
        const found = this.flatActivityMenu.find(
          (item) => item.value === categoryId
        );
        return found ? found.label : categoryId;
      }
      return categoryId;
    },
    /** 判断是否所有活动都被选中 */
    isAllActivitiesSelected(activityIds) {
      // 如果没有活动或者没有选择活动，则返回false
      if (
        !this.flatActivityMenu ||
        !this.flatActivityMenu.length ||
        !activityIds ||
        !activityIds.length
      ) {
        return false;
      }

      // 首先支持旧数据中可能存在的"all"标记
      if (activityIds.includes("all")) {
        return true;
      }

      // 获取所有可选活动的ID
      const allActivityIds = this.flatActivityMenu.map((item) => item.value);

      // 1. 检查是否选择的数量和总数量相同
      if (activityIds.length !== allActivityIds.length) {
        return false;
      }

      // 2. 检查每个可选活动是否都被选中
      return allActivityIds.every((id) => activityIds.includes(id));
    },
  },
};
</script>

<style scoped>
.mb8 {
  margin-bottom: 8px;
}

.checkbox-container {
  display: flex;
  flex-wrap: wrap;
}

.checkbox-item {
  width: 25%;
  margin-bottom: 8px;
  padding-right: 10px;
  box-sizing: border-box;
}

@media screen and (max-width: 768px) {
  .checkbox-item {
    width: 50%;
  }
}
</style>
